#ifndef __WED_GPIO_H__
#define __WED_GPIO_H__

#include "../Wed_dev.h"
#include "mem/Wed_mem.h"
#include "print/Wed_print.h"

#define WED_GPIO_OUTPUT_LOW_FLAG       (0)
#define WED_GPIO_OUTPUT_HIGH_FLAG      (1)
#define WED_GPIO_OUTPUT_STA_FLAG_MASK  (1)
#define WED_GPIO_OUTPUT_FLAG           (0 << 1)
#define WED_GPIO_INPUT_FLAG            (1 << 1)
#define WED_GPIO_DIR_FLAG_MASK         (1 << 1)

/* \brief GPIO 设备操作函数集 */
struct Wed_gpio_opts {
    int (*p_fn_init)(void *p_opts_arg, uint32_t port_num, uint32_t pin_num, uint32_t flag);
    int (*p_fn_sta_set)(void *p_opts_arg, uint32_t port_num, uint32_t pin_num, uint8_t sta);
    int (*p_fn_sta_toggle)(void *p_opts_arg, uint32_t port_num, uint32_t pin_num);
};

/* \brief GPIO 设备结构体 */
struct Wed_gpio {
    struct Wed_dev        dev;         /* 基础设备 */
    struct Wed_gpio_opts *p_opts;      /* GPIO 操作函数集 */
    void                 *p_opts_arg;  /* GPIO 操作函数参数 */
    uint32_t              port_num;    /* GPIO 端口号 */
    uint32_t              pin_num;     /* GPIO 引脚号 */
    struct Wed_mutex      lock;        /* 互斥锁 */
    struct Wed_list_node  node;        /* GPIO 设备节点 */
    uint32_t              flag;
};

/**
 * \brief GPIO 设备链表初始化
 *
 * @return 成功返回 0
 */
int Wed_gpio_list_init(void);
/**
 * \brief GPIO 设备注册函数
 *
 * @param p_gpio_name GPIO 名字
 * @param p_opts      GPIO 设备操作函数集
 * @param p_opts_arg  操作函数参数
 * @param port_num    GPIO 端口号
 * @param pin_num     GPIO 引脚号
 * @param flag        标志
 *
 * @return 成功返回 0
 */
int Wed_gpio_register(char                 *p_gpio_name,
                      struct Wed_gpio_opts *p_opts,
                      void                 *p_opts_arg,
                      uint32_t              port_num,
                      uint32_t              pin_num,
                      uint32_t              flag);
/**
 * \brief 初始化所有 GPIO
 *
 * @return 成功返回 0
 */
int Wed_gpio_init_all(void);
/**
 * \brief 根据名字获取 GPIO 设备结构体
 *
 * @param p_gpio_name GPIO 名字
 *
 * @return 找到返回 GPIO 设备结构体，没找到返回 NULL
 */
struct Wed_gpio *Wed_gpio_find_by_name(char *p_gpio_name);
/**
 * \brief GPIO 状态设置
 *
 * @param p_gpio GPIO 设备
 * @param sta    GPIO 状态
 *
 * @return 成功返回 0
 */
int Wed_gpio_sta_set(struct Wed_gpio *p_gpio, uint8_t sta);
/**
 * \brief GPIO 翻转
 *
 * @param p_gpio GPIO 设备
 *
 * @return 成功返回 0
 */
int Wed_gpio_toggle(struct Wed_gpio *p_gpio);
#endif


